package chat.util;

import chat.bean.Message;
import chat.constant.CommonConst;
import chat.constant.MessageType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;
import java.util.Optional;

@EqualsAndHashCode(callSuper = true)
@Data
@Slf4j
@AllArgsConstructor
public class ServerThread extends Thread {

    private Socket socket;

    @Override
    public void run() {
        try (
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
        ) {
            while (true) {
                //开始监听
                Optional<Message> message = MsgUtils.readMsg(inputStream);
                if (message.isPresent()) {
                    Message msg = message.get();
                    switch (msg.getType()) {
                        case MessageType.LOGIN:
                            loginHandler(msg, socket);
                            break;
                        case MessageType.EXIT:
                            exitHandler(msg, outputStream);
                            break;
                        case MessageType.TO_ALL:
                            sendMsgToAll(msg);
                            break;
                        case MessageType.TO_FRIEND:
                            sendMsgToFriend(msg, outputStream);
                            break;
                        case MessageType.REGISTER:
                            registerHandler(msg, outputStream);
                            break;
                        case MessageType.TO_SERVER:
                            sendMsgToServer(msg, outputStream);
                            break;
                        default:
                            break;
                    }
                }

            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 发送给服务端信息
     * 服务端响应给客户端
     *
     * @param msg
     * @param outputStream
     */
    private static void sendMsgToServer(Message msg, OutputStream outputStream) {
        String content = msg.getContent();
        String username = msg.getUsername();
        log.info("{}:{}", username, content);
        MsgUtils.writeMsg(outputStream, MsgUtils.createMsg(MessageType.SERVER, CommonConst.OK, CommonConst.SERVER));
    }

    /**
     * 注册
     *
     * @param msg
     * @param outputStream
     */
    private static void registerHandler(Message msg, OutputStream outputStream) {
    }

    /**
     * 发送给指定好友
     *
     * @param msg
     * @param outputStream
     */
    private static void sendMsgToFriend(Message msg, OutputStream outputStream) {
        String toFriend = msg.getToFriend();
        if (!CommonConst.ONLINE_USER.containsKey(toFriend)) {
            MsgUtils.writeMsg(outputStream, MsgUtils.createMsg(MessageType.SERVER, CommonConst.USER_NOT_FOUND, CommonConst.SERVER));
            log.info(CommonConst.USER_NOT_FOUND + ":" + toFriend);
            return;
        }
        Socket friendSocket = CommonConst.ONLINE_USER.get(toFriend);
        String content = msg.getContent();
        String username = msg.getUsername();
        log.info("{}:{}", username, content);
        try {
            OutputStream friendSocketOutputStream = friendSocket.getOutputStream();
            MsgUtils.writeMsg(friendSocketOutputStream, MsgUtils.createMsg(MessageType.SERVER, content, username));
            MsgUtils.writeMsg(outputStream, MsgUtils.createMsg(MessageType.SERVER, CommonConst.OK, CommonConst.SERVER));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 群发
     *
     * @param msg
     */
    private static void sendMsgToAll(Message msg) {
        Map<String, Socket> onlineUser = CommonConst.ONLINE_USER;
        onlineUser.forEach((key, socket) -> {
            try {
                MsgUtils.writeMsg(socket.getOutputStream(), MsgUtils.createMsg(MessageType.SERVER, msg.getContent(), msg.getUsername()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            };
        });
    }

    /**
     * 退出登录
     *
     * @param msg
     * @param outputStream
     */
    private static void exitHandler(Message msg, OutputStream outputStream) {
    }


    /**
     * 登录
     * 登录成功后提示客户端登录成功
     *
     * @param msg
     * @param socket
     */
    private void loginHandler(Message msg, Socket socket) {
        String username = msg.getUsername();
        String password = msg.getPassword();
        try {
            OutputStream outputStream = socket.getOutputStream();
            if (StringUtils.equals(CommonConst.DEFAULT_PASSWORD, password)) {
                CommonConst.ONLINE_USER.put(username, socket);
                log.info("用户【{}】登录成功", username);
                MsgUtils.writeMsg(outputStream, new Message(MessageType.CLIENT, CommonConst.SUCCESS, CommonConst.SERVER));
                return;
            }
            log.info("用户【{}】登录失败", username);
            MsgUtils.writeMsg(outputStream, new Message(MessageType.CLIENT, CommonConst.FAIL, CommonConst.SERVER));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
